package com.elysia.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.elysia.common.Result;
import com.elysia.mapper.FilesMapper;
import com.elysia.entity.Files;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

@RestController
@RequestMapping("/files")
public class FileController {

    //从yml文件中读取path的地址
    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Value("${server.ip}")
    private String serverIp;

    @Autowired
    private FilesMapper filesMapper;


    /**
     * 文件的上传
     * @param file
     * @return 返回文件路径地址
     */
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        //获取源文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件的后缀名
        String type = FileUtil.extName(originalFilename);
        //获取文件的大小
        long size = file.getSize();

        //定义一个文件唯一的标示码
        //简化的UUID，去掉了横线，使用性能更好的ThreadLocalRandom生成UUID
        String uuid = IdUtil.fastSimpleUUID();
        //拼接uuid：uuid+“.”+后缀名
        String fileUUID = uuid + StrUtil.DOT + type;
        //创建文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        //判断配置的文件目录是否存在 若不存在则创建一个新的目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()){
            parentFile.mkdirs();
        }

        String url;
        //获取文件的md5
        String md5 = SecureUtil.md5(file.getInputStream());
        //从数据库查询是否存在相同的记录
        Files dbFiles = getFileByMd5(md5);
        if (dbFiles != null){
            url = dbFiles.getUrl();
        } else {
            //上传文件到磁盘
            file.transferTo(uploadFile);
            //数据库若不存在重复文件 则不删除刚才上传的文件
            url = "http://"+serverIp+":9091/files/" + fileUUID;
        }

        //存入数据库
        Files saveFile = new Files();
        saveFile.setName(originalFilename);
        saveFile.setType(type);
        saveFile.setSize(size/1024);//文件大小按kb来算
        saveFile.setUrl(url);
        saveFile.setMd5(md5);
        saveFile.setIsDelete(false);
        filesMapper.insert(saveFile);

        return url;
    }

    /**
     * 通过文件的md5查询文件
     * @param md5
     * @return 返回查询的数据
     */
    private Files getFileByMd5(String md5) {
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5",md5);
        List<Files> filesList = filesMapper.selectList(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }

    /**
     * 文件下载
     * http://localhost:9091/file/{fileUUID}
     * @param fileUUID 文件id
     * @param response
     */
    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        //根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        //设置输出流格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        //读取文件字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * 更新操作
     * @param files 文件
     * @return 返回更新成功信息
     */
    @PostMapping("/update")
    public Result update(@RequestBody Files files){
        return Result.success(filesMapper.updateById(files));
    }

    /**
     * 删除
     * @param id 文件id
     * @return 返回删除成功的信息
     */
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id){
        //根据id查询
        Files files = filesMapper.selectById(id);
        //确认删除
        files.setIsDelete(true);
        //根据id更新信息
        filesMapper.updateById(files);
        return Result.success();
    }

    /**
     * 批量删除
     * @param ids id集合
     * @return 返回批量删除成功信息
     */
    @PostMapping("/del/ids")
    public Result deleteByIds(@RequestBody Integer[] ids){
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",ids);
        List<Files> files = filesMapper.selectList(queryWrapper);
        for (Files file : files) {
            file.setIsDelete(true);
            filesMapper.updateById(file);
        }

        return Result.success();
    }

    /**
     * 分页查询
     * @param pageNum 页码数
     * @param pageSize 页码大小
     * @param name 名字
     * @return 返回查询的页码，页码数
     */
    @GetMapping("/findPage")
    public Result findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize,
                           @RequestParam (defaultValue = "") String name){

        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete",false);

        //如果名字不为"" 那么就根据name进行模糊查询
        if (!"".equals(name)){
            queryWrapper.like("name",name);
        }

        return Result.success(filesMapper.selectPage(new Page<>(pageNum,pageSize),queryWrapper));
    }
}
